Identity Tokens #
The JSON Web Token #
JSON Web Tokens (JWT), pronounced “jot”, are a standard since the information they carry is transmitted via JSON. We can read more about the draft specification, but that explanation isn’t the most pretty to look at. JWTs essentially encode any sets of identity claims into a payload, provide some header data about how it is to be signed, then calculate a signature using one of several algorithms and append that signature to the header and claims.
JWT’s are used and supported widely in software because:
- JSON Web Tokens work across many different programming languages: JWTs work in .NET, Python, Node.js, Java, PHP, Ruby, Go, JavaScript, and Haskell. So you can see that these can be used in many different scenarios.
- JWTs are self-contained: They will carry all the information necessary within itself. This means that a JWT will be able to transmit basic information about itself, a payload (usually user information), and a signature.
- JWTs can be passed around easily: Since JWTs are self-contained, they are perfectly used inside an HTTP header when authenticating an API. You can also pass it through the URL
When are they used? #
JWT’s can be used in many scenarios; however, they are most commonly used for the following purposes:
- Authorization: This is the most common scenario for using JWT. Once the user is logged in, each subsequent request will include the JWT, allowing the user to access routes, services, and resources that are permitted with that token. Single Sign On is a feature that widely uses JWT nowadays, because of its small overhead and its ability to be easily used across different domains.
- Information Exchange: JSON Web Tokens are a good way of securely transmitting information between parties. Because JWTs can be signed—for example, using public/private key pairs—you can be sure the senders are who they say they are. Additionally, as the signature is calculated using the header and the payload, you can also verify that the content hasn’t been tampered with.
How they work #
In authentication, when the user successfully logs in using their credentials, a JSON Web Token will be returned. Since tokens are credentials, great care must be taken to prevent security issues. In general, you should not keep tokens longer than required.
Whenever the user wants to access a protected route or resource, the user agent should send the JWT, typically in the Authorization header using the Bearer schema. The content of the header should look like the following:
Authorization: Bearer <token>
This can be, in certain cases, a stateless authorization mechanism. The server’s protected routes will check for a valid JWT in the Authorization header, and if it’s present, the user will be allowed to access protected resources. If the JWT contains the necessary data, the need to query the database for certain operations may be reduced, though this may not always be the case.
If the token is sent in the Authorization header, Cross-Origin Resource Sharing (CORS) won’t be an issue as it doesn’t use cookies.
The following shows a basic diagram of how tokens are used and validated by software:
What do they look like? #
A JWT is easy to identify. It is simply three strings which are separated by periods (.).
For example:
aaaa.bbbbbbbb.ccccccccc
Since there are three parts separated by a period (.), each section serves a specific purpose and is used differently. The three parts consist of:
- the header
- the payload
- the signature
THE HEADER #
The header typically contains information about how the JWT was created. This includes things like the cryptographic sets used, keys types, and the like. Essentially, this section is used to provide all the information necessary to verify and validate the rest of the JWT. Typically, there are from 2 - 5 keys in this section depending on the exact implementation and use case.
Here is an example of a sample typical header section you might commonly see:
// Sample JWT Header Section
{
"typ": "JWT",
"alg": "HS256",
"x5t": "LqtvoOPBIKtWfiFZUnq1g0bTOC0",
"kid": "2EQB6FA0E3C120AB567E215927AB58106D3382D"
}
// Base64 Encoded header - the header above
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsIng1dCI6IkxxdHZvT1BCSUt0V2ZpRlpVbnExZzBiVE9DMCIsImtpZCI6IjJFUUI2RkEwRTNDMTIwQUI1NjdFMjE1OTI3QUI1ODEwNkQzMzgyRCJ9
This sample header contains 4 items:
- typ - this is the type of token. Here it is identified as a JWT
- alg - the hashing algorithm used
- kid - Key Identifier – Acts as an ‘alias’ for the key
- x5t - X.509 Certificate Thumbprint – Used to identify specific certificates
Most commonly, the algorithms used for signing JWTs are based upon public/private key cryptography. This facilitates a centralized identity provider (such as AAD B2C), which holds the private key, to issue signed tokens which can be validated by remote services using the public key, without them needing to communicate back to the identity provider more than once. There are, of course as with everything in software, alternatives to this approach, although they are less commonly used and will not be covered here.
THE PAYLOAD #
The payload will carry the bulk of our JWT, also called the JWT Claims. This is where we will put the information that we want to transmit and other information about our token.
Claims are predefined keys and their values. There are three types of claims: registered, public, and private claims.
Registered ClINA #
These are a set of predefined keys which are not mandatory but recommended. They are strictly reserved and, if included, should only be used for there intended purpose. These registered claims include:
- iss: The issuer of the token
- sub: The subject of the token
- aud: The audience of the token
- exp: This will probably be the registered claim most often used. This will define the expiration in NumericDate value. The expiration MUST be after the current date/time.
- nbf: Defines the time before which the JWT MUST NOT be accepted for processing
- iat: The time the JWT was issued. Can be used to determine the age of the JWT
- jti: Unique identifier for the JWT. Can be used to prevent the JWT from being replayed. This is helpful for a one time use token.
Public Claims #
These are the claims that we create ourselves like user name, information, and other important information. These can be defined at will by those using JWTs. But to avoid collisions they should be defined in the IANA JSON Web Token Registry or be defined as a URI that contains a collision resistant namespace.
Private Claims #
These are the custom key value pairs created to share information between parties that agree on using them and are neither registered or public claims. In general, we should avoid using private claims as they are subject to collision.
Our example payload has three registered claims (iss, sub, and exp) and two public claims (name and admin):
// Sample Payload
{
"iss": "sphera-id.com",
"exp": 1300819380,
"sub": "1234567890",
"name": "Perry Marchant",
"admin": true
}
// Base64 Encoded payload of above
eyJpc3MiOiJzcGhlcmEtaWQuY29tIiwiZXhwIjoxMzAwODE5MzgwLCJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IlBlcnJ5IE1hcmNoYW50IiwiYWRtaW4iOnRydWV9
This becomes the second part of our JWT.
THE SIGNATURE #
The third and final part of our JSON Web Token is going to be the signature. The signature is used to verify that the sender of the JWT is who it says it is and to ensure that the message wasn’t changed along the way. To create the signature part you have to take the encoded header, the encoded payload, a secret, the algorithm specified in the header, and sign it. Basically, this is a sample of how we generate a signature:
// basic method to generate a signature key
var encodedString = base64UrlEncode(header) + "." + base64UrlEncode(payload);
HMACSHA256(encodedString, 'secret');
// Encoded sample signature of above
OJeJOI21taNymu42ps-QwRVBuX6Egsqck5CGCMgVUd0
Now that we have the three parts and they are all encoded correctly, we can put them together to make a full JWT that can be passed via a header in our http requests.
var token = `${enc_header}.${enc_payload}.${signature}`;
// Final Header
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOiIyMDE5LTAyLTE0IiwibWVzc2FnZSI6InJvc2VzIGFyZSByZWQifQ.0u-mkgLo5479CPjJJ4mXCwn2RW4dFT12fiYiopRWsZw
Something important to remember here is that JWT tokens are used for authentication and not encryption, so even without knowing the secret key, someone can read your header and payload data.
But upon receiving the token you can sign the header and payload again with your secret key and compare it with the received signature to detect tampering of token or the message.
A good place to start will be by going to this online JWT debugger at jwt.io and play around with some tokens to get a feel for how they work.
f you want to learn more about JSON Web Tokens and even start using them to perform authentication in your own applications, browse to the JSON Web Token landing page at Auth0 or at JWT.io.